import base64
import json
import os
import queue

import locust
from locust import task, HttpUser, constant, tag, TaskSet

from common.utils import decode64_str
from testcases.api_stress.api_stress import log






class RunTasks(HttpUser):
    wait_time = constant(10)
    host = "https://www.retone-hearing.fit"
    header = {"Content-Type": "application/json"}
    tester = 'tester9697'

    @task
    @tag('login')
    def login(self):
        pass

    @task
    @tag('get_personal_info')
    def get_personal_info(self):
        """
        获取各人信息
        :param username: 用户名
        :param passwd: 密码
        :return: 返回mqtt配置信息
        """
        mqtt_url = '/platformRetoneFit/api/needAppUserAuth/responseEncode/requestDecode/getCurrentPersonalInfo'
        info = {}
        res = self.send_post(mqtt_url, info, name="获取个人信息")
        if res.status_code != 200 or res.json()['data'] is None:
            log.info(f'=====  获取个人  信息接口失败 =========\n状态码={res.status_code},错误信息={res.json()}')
        else:
            data_str = decode64_str(res.json()['data'])
            data = json.loads(data_str)
            # log.info(dic_conf)
            log.info(f'data={data}')
            return data

    @task
    @tag('modify')
    def modifypersoninfo(self, cookie, account=None, name=None, gender=None) -> None:
        """
        | account   | String  | chen123  |   否   | 账号。<br>验证规则：只允许英文、数字、特殊字符_-+~!@#$%^&*，且4-30个字符，非纯数字 |
        | name      | String  | 张三  |   否   |姓名<br>最大长度：20 |
        | gender   | GenderEnum | MALE |   否  | 性别。MALE：男、FEMALE：女、null：空 |
        :return:
        """
        account = account if account else "tester9697"
        name = name if name else "testing"
        gender = gender if gender else "MALE"
        url = '/microServiceUser/needAppUserAuth/responseEncode/requestDecode/modifyPersonInfo'
        data = {
            "account": account,
            "name": name,
            "gender": gender
        }
        res = self.send_post(url, data, name="修改个人信息", cookie=cookie)
        if res.status_code != 200 or res.json()['result'] != '200':
            log.info('============= 修改个人信息 接口错误, 请检查================')
            log.info(f'返回状态码:{res.status_code},错误的内容:{res.text}')
        else:
            log.info(f'修改信息成功')

    @task
    @tag('modify')
    def modifypassword(self, cookie, oldPassword, newPassword) -> None:
        """新旧密码
        | oldPassword | String  | 123456 |  是  | 旧密码 |
        | newPassword | String  | 000000 |  是  | 新密码 <br>验证规则：只允许英文、数字、特殊字符_-+~!@#$%^&*，且6-30个字符，必须同时包含数字和字母 |
        :param cookie:
        :param oldPassword:
        :param newPassword:
        :return:
        """
        oldPassword = oldPassword if oldPassword else "cc1234"
        newPassword = newPassword if newPassword else "cc1234"
        url = '/microServiceUser/needAppUserAuth/responseEncode/requestDecode/modifyPersonPassword'
        data = {
            "oldPassword": oldPassword,
            "newPassword": newPassword
        }
        res = self.send_post(url, data, name="修改密码", cookie=cookie)
        if res.status_code != 200 or res.json()['result'] != '200':
            log.info('============= 修改密码 接口错误, 请检查================')
            log.info(f'返回状态码:{res.status_code},错误的内容:{res.text}')
        else:
            log.info(f'修改密码成功,新密码:{data["newPassword"]}')

    @task
    @tag('login_status')
    def getLoginState(self, cookie=None) -> bool:
        """
        :param cookie:
        :return: Ture or False
        """
        url = '/microServiceUser/responseEncode/requestDecode/getLoginState'
        res = self.send_post(url, name="获取登录状态", cookie=cookie, )
        if res.status_code != 200 or res.json()['result'] != '200':
            log.info('============= 获取登录状态 接口错误, 请检查================')
            log.info(f'返回状态码:{res.status_code},错误的内容:{res.text}')
        else:
            dic = json.loads(decode64_str(res.json()['data']))
            log.info(f'APP登录状态:{dic["loginState"]}')
            return dic["loginState"]

    @task
    @tag('user_status')
    def getUserLoginObjectState(self, account, phonecountry=None, sourceplatform=None) -> dict:
        """验证APP用户登录主体是否存在
        | loginObject | String | 18566965369 | 是 |登录对象。可以是账号、手机号、邮箱中的任意一种。 <br>账号验证规则：只允许英文、数字、特殊字符_-+~!@#$%^&*，且4-30个字符，非纯数字<br>手机号长度：4-12位<br>邮箱最大长度：50|
        | phoneCountry | Enum | CN   | 否 | 手机号归属国家(用户登录主体是手机号时必填时必填)<br>CN：中国<br>OTHER：其它|
        | sourcePlatform  | Enum | RETONE_FIT | 是 | 验证来源平台。<br>RETONE_FIT：RetoneFit<br>BLUETOOTH_HA：BluetoothHA<br>WECHAT_HA：WeChatHA|
        :param cookie:
        :return:
        | loginObjectState  | Boolean  | true | 用户登录主体是否存在。true:已存在、false:不存在 |
        | userCancellation  | Boolean  | true | 用户是否是注销状态（只有loginObjectState为true时才有值）。true:注销、false:非注销 |
        """
        account = account if account else f"{self.tester}"
        phonecountry = phonecountry if phonecountry else 'CN'
        sourceplatform = sourceplatform if sourceplatform else "RETONE_FIT"
        url = '/microServiceUser/responseEncode/requestDecode/getUserLoginObjectState'
        data = {
            "loginObject": account,
            "phoneCountry": phonecountry,
            "sourcePlatform": sourceplatform
        }
        res = self.send_post(url, data, name="验证APP用户登录主体是否存在")
        if res.status_code != 200 or res.json()['result'] != '200':
            log.info('============= APP用户登录主体是否存在 接口错误, 请检查================')
            log.info(f'返回状态码:{res.status_code},错误的内容:{res.text}')
        else:
            dic = json.loads(decode64_str(res.json()['data']))
            log.info(f'用户登录主体是否存在:{dic["loginObjectState"]}, 用户是否是注销状态:{dic["userCancellation"]}')
            return dic

    @task
    @tag("upload_file")
    def uploadUserProfile(self, cookie, image_path) -> None:
        """
        上传用户头像
        :param cookie:
        :param files:
        :return:
        """
        image_path = image_path if image_path else r"C:\Users\Administrator\Pictures\R-C.jpg"
        url = '/microServiceUser/needAppUserAuth/responseEncode/uploadUserProfile'
        with open(image_path, mode='rb') as image:
            image_rb = image.read()
        files = {'file': image_rb}
        res = self.client.post(url, files=files, cookies=cookie)
        if res.status_code != 200 or res.json()['data'] is None:
            log.info('============= 上传文件 接口错误, 请检查================')
            log.info(f'返回状态码:{res.status_code},错误的内容:{res.text}')
        else:
            dic = json.loads(decode64_str(res.json()['data']))
            log.info(f'文件路径:{dic["filePath"]}, 文件展示路径:{dic["filePathShow"]}')
            return dic

    """
    retonet fit
    """

    @task
    @tag('addmemo')
    def addmemo(self, cookie=None, note=None, activeTime=None, memoTypeEnum=None, dayofweeks=None):
        """
        | note      | String  | 记得煮饭  |   是   |提醒内容<br>最大长度：255个字符 |
        | activeTime| String  | 2021-03-26 08:23:20  |   是   |提醒时间 格式："yyyy-MM-dd HH:mm:ss" 【注意：app上传时间为0时区时间】|
        | memoTypeEnum   | Enum | NEVER_REPEAT |   是  | 备忘录类型。<br>NEVER_REPEAT：不重复、<br>EVERY_DAY：每天、
        <br>WORK_DAY：工作日（周一-周五）、<br>REST_DAY：休息日（周六-周日）、<br>DAY_OF_WEEK：每周指定时间（周一-周日） |
        | dayOfWeeks  | List<Enum> | ["SUNDAY"] |   否  | 每周指定时间（周一-周日）。只有在“备忘录类型”是 “每周指定时间”的情况下才必填。
        <br>SUNDAY：周日<br>MONDAY：周一<br>TUESDAY：周二<br>WEDNESDAY：周三<br>THURSDAY：周四<br>FRIDAY：周五<br>SATURDAY：周六|
        :return:
        """
        note = note if note else "出门"
        activeTime = activeTime if activeTime else '2023-02-15 11:11:00'
        memoTypeEnum = memoTypeEnum if memoTypeEnum else 'EVERY_DAY'
        if memoTypeEnum == "DAY_OF_WEEK":
            dayofweeks = dayofweeks if dayofweeks else 'SUNDAY'
        addmemo_url = '/api/memo/needAppUserAuth/responseEncode/requestDecode/addMemo'
        info = {
            "note": note,
            "activeTime": activeTime,
            "memoTypeEnum": memoTypeEnum,
            "dayOfWeeks": dayofweeks
        }
        res = self.send_post(addmemo_url, data=info, name='新增备忘提醒', cookie=cookie)
        result = self.assert_result(res)

    @task
    @tag('set')
    def bind_set(self, cookie, devicenum):
        """
        绑定设备 设备型号可以随机生成
        :return: 返回绑定设备
        """
        bind_set_url = '/platformRetoneFit/api/deviceBinding/needAppUserAuth/responseEncode/requestDecode/binding'
        info = {
            "deviceNumber": devicenum,
            "deviceTypeCode": "1",
            "chipTypeCode": "1"
        }
        res = self.send_post(bind_set_url, info, name="绑定设备", cookie=cookie)
        if res.status_code != 200 or res.json()['description'] is not None:
            log.info("============= 绑定设备 错误==========")
            log.info(res.json())
        return info['deviceNumber']

    @task
    @tag('set')
    def use_set(self, cookie, devicenum):
        """
        使用设备的信息, 使用设备的用户
        :param cookie: 用户
        :return:
        """
        user_set_url = '/platformRetoneFit/api/deviceBinding/needAppUserAuth/responseEncode/requestDecode/deviceUse'
        info = {
            "leftDevice": {
                "deviceNumber": devicenum,
                "firmwareVersion": "1.0.38"
            },
            "rightDevice": {
                "deviceNumber": devicenum,
                "firmwareVersion": "1.0.38"
            }
        }
        res = self.send_post(user_set_url, info, cookie)
        # data = decode64_str(res.json()['data'])
        # data = json.loads(data)
        if res.status_code != 200 or res.json()['data'] is None:
            log.info('===使用设备接口 错误== ')
            log.info(res.json())

    @task
    @tag('set')
    def check_device(self, cookie):
        check_devices_url = '/platformRetoneFit/api/deviceBinding/needAppUserAuth/responseEncode/requestDecode/getDeviceBindingList'
        info = {}
        res = self.send_post(check_devices_url, info, name="检查设备", cookie=cookie)
        if res.status_code != 200 or res.json()['data'] is None:
            log.info(res.json())
            log.info('==========查询绑定设备信息出现错误  =====')
        else:
            data = decode64_str(res.json()['data'])
            data = json.loads(data)
            log.info(data)

    def on_start(self):
        """
        登录接口
        :param username: 用户名
        :param password: 密码
        :return: 返回用户cookie
        """
        # 登录
        login_url = '/microServiceUser/responseEncode/requestDecode/login'
        info = {
            "type": 0,
            "sourcePlatform": "RETONE_FIT",
            "password": 'cc1234',
            "loginObject": f'{self.tester}'
        }
        res = self.send_post(login_url, info, name="登录")
        if res.status_code != 200 or res.json()['data'] is None:
            log.info("=============  登录   接口调用失败==========" + '\n' + str(
                res.json()) + f'res.status_code = {res.status_code}')
        # else:
        #     with open('cookie.txt', mode='a', encoding='utf8') as f:
        #         f.write(res.cookies.values()[0] + '\n')
        #     return str(res.cookies.values()[0])

    def assert_result(self, res):
        if res.status_code != 200 or res.json()['data'] is None:
            print('结果有误')
        else:
            pass
        return res

    def send_post(self, url, data, name=None, cookie=None):
        data = self.bs64(data)
        if cookie is None:
            res = self.client.post(url, data=data, headers=self.header)
        else:
            res = self.client.post(url, data=data, headers=self.header, cookies=cookie)
        return res

    def bs64(self, data):
        data = json.dumps(data, ensure_ascii=False)
        encode64 = base64.b64encode(data.encode('utf-8'))
        return encode64.decode('utf-8')


if __name__ == '__main__':
    os.system('locust -f fasttest.py --tag get_personal_info --web-host="127.0.0.1"')
